Building a database deployment pipeline with AI assistance sounds straightforward…until the AI starts treating temporary security shortcuts as permanent architecture.
In part three of his series on building an app and database almost entirely through an LLM, Grant Fritchey walks through using GitHub Copilot and VSCode to configure Redgate Flyway for PostgreSQL on Azure Flexible Server, provision a self-hosted GitHub Actions runner inside a private VNet, and wire it all together into an automated CI/CD pipeline.
The result is impressively functional — but the process surfaces a critical lesson: AI coding assistants are fast, capable, and dangerously confident about security decisions they have no business making alone.
Find the full repo, including every prompt, on GitHub.
Since I’m starting development on the database side of dbRosetta, and since I’m much more comfortable with databases than with code, I’m going to stay in the database sphere for a bit.
My next step is to work with the AI to get a pipeline in place to deploy our database code to Azure Flexible Server. I’m using Redgate Flyway as the database automation tool because I’m comfortable with it (also, because it’s the best DB deployment tool out there — fight me).
Setting up Flyway
I went straight to Microsoft Copilot – my main AI companion for this experiment – and asked it to generate the prompt I’d need for VSCode. However, I did a bad job on my own prompt. See if you can spot the problem:
Can you give me a prompt for VSCode, using the agreed prompt structure that you helped me build, to create a Flyway Enterprise baseline and initial set of migrations based on reverse engineering using Flyway Compare technology, to capture the existing database we created earlier through the Flyway CLI?
It might not be obvious why this prompt is bad. In fact, Copilot generated a perfectly reasonable VSCode prompt from that – versioned migration naming, non-destructive baseline, CI-friendly output, validation step. So, what’s wrong?
Well, I didn’t specify what I wanted for development versus production environments – so it’s treating them all the same. This is something we’ll need to fix later. Isn’t it great that, even with AI, we can still introduce code debt!
Deploy with confidence with Redgate Flyway
Giving the bad prompt to VSCode
I fed the prompt into VSCode. It went to work. It knows how to connect up to my Azure Flexible Server, so it ran `pg_dump` to get the SQL file for the baseline (I’d assumed it would use Flyway for this – it surprised me). And it then built out the `*.toml` file for controlling Flyway, and ran a baseline command against my database using the migrations it had created.
It didn’t work flawlessly. It made a mistake in the configuration. Then, since it had provided multiple test steps, it fixed it. I’m not kidding. So, yeah, I’ve got a Flyway migration harness ready to go.
There may be more that’s needed down the road to automate this fully, but I’m not going to lie – I’m surprised at what I’ve got so far. Pleasantly so.
Creating a pipeline
When I’ve set these up myself, I get Flyway configured and functional first, then figure out how to get it to run inside the pipeline I create. Talking with Copilot, it wanted me to prompt it, to enable it to build the GitHub Actions. It is weird talking to one to talk to the other, but it’s working gangbusters so far!
I did have to remind it that, only earlier, it had told me we’d need to set up a VM (virtual machine) inside my VNet (virtual network) to be a self-hosted GitHub runner…
I’ve noticed these things don’t do a flawless job of maintaining context. It falls back on us – at least in my experience so far – to be extremely thorough in our prompts in order to get the best results. However, it remembers again that we’re behind a firewall.
(And yes, before anyone asks, I’m using the paid tier for this adventure. I have to imagine the free tier may be even more forgetful.)
What Copilot eventually produced
The prompt Copilot eventually produced was a self-hosted runner spec: cheapest viable Azure VM (Standard_B1s, ~$7.50/month), no public IP, system-managed identity, secrets fetched from Key Vault at runtime via OpenID Connect (OIDC). Sensible. Over to VSCode…
This time it chose to create everything as bash scripts. The first one ran cleanly and provisioned the VM, security group, network interface and VNet. On to the next script…
This one involved a lot of setup within the VM, where VSCode can’t help me as an agent — so I did a lot of typing from VSCode prompts. Now I’m the AI. Ha!
The interesting thing was the troubleshooting. The AI didn’t get everything right the first time, although I may have introduced a typo or three. Troubleshooting, however, was actually pretty outstanding. I’d feed it errors and it would feed me solutions (or additional checks followed by solutions.)
Most of the rest of this was very interactive. Some work was readily done by GitHub Copilot acting as an agent inside VSCode. And some was me getting certificates and other things that couldn’t readily be retrieved through Copilot.
When temporary becomes permanent (the security issues triggered by the AI)
It was interesting how much I had to remind the AI of things. For example, it wanted to test what we’d done, but only supported a `Development` or `Production` branch. Its first inclination was to add the branch we were working on, but that branch wouldn’t be permanent, so I had to remind it that we could do it for a test but it had to be easily undone.
Then, we hit a security problem on our PostgreSQL cluster.
It wanted to use the public IP address we had temporarily added to our VM. It was like, once a thing was done and available, that thing was permanently part of the project – despite the stated purpose being a temporary thing for setup.
The conversation went something like this:
Me: Instead of the public IP address, shouldn’t we do something within Azure to let the resource access it since the IP address is temporary for the setup?
Copilot: Excellent point! You’re absolutely right. Since both the VM and PostgreSQL are in Azure, we should use VNet integration or Azure service endpoints instead of relying on the public IP.
[Copilot then investigated and pivoted to suggesting the `0.0.0.0` “AllowAzureServices” firewall rule.]
Copilot: Perfect! The firewall rule `0.0.0.0` is a special Azure rule that allows all Azure services (including VMs in the same subscription) to connect to the PostgreSQL server. This is the Azure-native way to allow internal Azure resources to communicate.
The latter is the kind of suggestion you want to pay close attention to – but why?
Well, the 0.0.0.0 rule allows access from *any* Azure subscription, not just yours. It’s one of the more commonly cited misconfigurations in cloud security write-ups.
For a hobby project with no production data, the risk is small. For an engineer in their first job, however, copying this pattern into a real codebase because the AI called it the “Azure-native way,” the risk is most certainly not small.
In this instance, I pushed back, but only because I knew to push back. We ended up with a sensible VNet-based path instead.
This was actually a common pattern across the whole step. Once the AI had something working – a temporary IP rule, a test branch in a deployment config, a one-off setup script – its instinct was to fold it into the architecture rather than flag it for removal.
That’s simply because scaffolding and architecture look identical to an LLM (large language model). Both are *code that exists in the project*. The distinction lives in your head, not the model’s.
Summary: I’m very impressed – but security continues to be an issue
Overall, I’m blown away. Most snags were not because the AI hallucinated, or was horribly wrong, but instead from licensing, permissions, and stuff I didn’t define while I was writing prompts to both AIs. The silly thing was pretty darn helpful.
I let it do troubleshooting I was perfectly capable of doing myself, because I wanted to see it work things out. And it did. Quite well.
AI is coming for your job… IF you’re not real good at your job. I could have done every bit of this work, but using GitHub Copilot made it a lot faster and easier.
However, I had to be on top of it. I had to track everything, because it didn’t always. It was more than ready to compromise security, multiple times. I couldn’t have just let it run. And this is a point I keep coming back to. The AI is a particularly brilliant, but extremely junior, developer on my team.
It’s lightning fast. It’s often correct. But it’s confidently wrong in exactly the places that matter most – and especially around the things that are “temporary for now”, but that no junior developer has the experience to flag.
You don’t let a junior developer near production secrets without supervision. You don’t let them make the call on networking topology. The same goes here, with the AI. That’s why humans are still so valuable (at least for the moment). We’re not just employed – we’re necessary!
In the next article, we’ll begin actually building the application. See you there.
Enjoying this article? Subscribe to the Simple Talk newsletter
FAQs: AI can build the pipeline, but don't trust it for security (building an app with an AI LLM, part three)
1. What is Redgate Flyway and why is it used for database deployments?
Redgate Flyway is a database migration and version control tool. It manages schema changes through numbered migration scripts, making deployments repeatable and auditable. In this project, Flyway Enterprise is used alongside Azure PostgreSQL Flexible Server to create a baseline from an existing database and apply controlled migrations through a CI/CD pipeline.
2. Can GitHub Copilot set up a GitHub Actions pipeline automatically?
Partially. Copilot can generate the YAML, bash scripts, and configuration files needed for a pipeline, and can troubleshoot errors when you feed them back. However, it requires careful human oversight — in this project it needed reminders about VNet constraints, self-hosted runner requirements, and security configurations it was getting wrong.
3. What security risks can AI assistants introduce in cloud infrastructure setup?
A common pattern is treating temporary scaffolding as permanent architecture. In this case, Copilot suggested using the 0.0.0.0 PostgreSQL firewall rule — which grants access to all Azure subscriptions, not just your own — and described it as the “Azure-native” approach. A developer without prior cloud security experience could easily copy that pattern into production. The correct solution was a VNet-based private connection.
4. Do AI coding tools maintain context across a long conversation?
Not reliably. In this project, Copilot would forget earlier constraints (such as the self-hosted runner requirement or the temporary nature of a public IP) and needed to be re-prompted. Writing thorough, explicit prompts and tracking decisions yourself remains essential.
5. Is AI going to replace database engineers?
No – not experienced ones. AI functions like a fast, confident junior developer — useful for acceleration, but dangerous without supervision. It can’t distinguish scaffolding from production architecture, and it lacks the instinct to flag security or design decisions for review. Human expertise remains the necessary check.
This document contains proprietary information and is protected by copyright law.
Copyright © 2026 Red Gate Software Limited. All rights reserved
Load comments